﻿
namespace ZDS

open System
open System.Collections
open System.Collections.Generic

module ZLinkStackModule =
    type ZLnkStackIterator<'t>(m_top : ZLnkLstNode<'t>) =
        let mutable m_cursor = m_top
        let mutable m_lastValue = Unchecked.defaultof<'t>

        interface IDisposable with
            member this.Dispose() =
                ()

        interface IEnumerator<'t> with
            member this.Current =
                m_lastValue

        interface IEnumerator with
            member this.MoveNext() =
                if m_cursor = null then
                    false
                else
                    m_lastValue <- m_cursor.Value
                    m_cursor <- m_cursor.Next
                    true

            member this.Reset() =
                m_cursor <- m_top

            member this.Current =
                box (this :> IEnumerator<'t>).Current

open ZLinkStackModule
type ZLinkStack<'t>() =

    // ######################### primary constructor
    // comparing with the LinkList, LinkStack's top is similar as LinkList's preHead
    // but different from LinkList, in LinkStack there is no extra "preHead"
    // all nodes in the stack will store meaningful data
    let mutable m_top : ZLnkLstNode<'t> = null 
    let mutable m_size = 0

    // ######################### members
    member this.Size = m_size

    member this.Push value =
        let newtop = new ZLnkLstNode<'t>(value,Next = m_top)
        m_top <- newtop
        m_size <- m_size + 1

    member this.Pop() =
        if m_top = null then
            raise <| ZError(ErrorCode.Empty)

        let value = m_top.Value
        m_top <- m_top.Next
        m_size <- m_size - 1
        value

    interface IEnumerable<'t> with
        member this.GetEnumerator() =
            new ZLnkStackIterator<'t>(m_top) :> IEnumerator<'t>

    interface IEnumerable with
        member this.GetEnumerator() =
            new ZLnkStackIterator<'t>(m_top) :> IEnumerator

